﻿#region

using System;
using System.Collections.Generic;

#endregion

namespace Radovici.SharedLibrary
{
    public class Progressable : Notifiable
    {
        #region Private fields

        private readonly List<string> _statusBarMessages = new List<string>();

        #endregion

        protected IList<string> StatusBarMessages
        {
            get { return _statusBarMessages; }
        }

        public bool IsCalculating
        {
            get
            {
                lock (_statusBarMessages)
                {
                    return _statusBarMessages.Count > 0;
                }
            }
        }

        public virtual string Status
        {
            get
            {
                string status = string.Empty;
                lock (_statusBarMessages)
                {
                    _statusBarMessages.ForEach(s => status += s + ", ");
                }
                if (status.EndsWith(", "))
                {
                    status = status.Substring(0, status.Length - ", ".Length);
                }
                return status;
            }
        }

        #region Private status functionality

        private void AddStatus(object status)
        {
            var s = status as string;
            if (s != null)
            {
                lock (_statusBarMessages)
                {
                    _statusBarMessages.Add(s);
                }
                NotifyIsCalculating();
            }
        }

        private void RemoveStatus(object status)
        {
            var s = status as string;
            if (s != null)
            {
                lock (_statusBarMessages)
                {
                    if (_statusBarMessages.Contains(s))
                    {
                        _statusBarMessages.Remove(s);
                    }
                }
                NotifyIsCalculating();
            }
        }

        private void NotifyIsCalculating()
        {
            Notify("IsCalculating");
            Notify("Status");
        }

        #endregion

        #region Nested type: ProgressableState

        public class ProgressableState : IDisposable
        {
            #region Private fields

            private readonly Action _callback;
            private readonly Progressable _parent;
            private readonly object _state;
            private readonly string _status;

            #endregion

            public ProgressableState(Progressable parent, object state, string status)
                : this(parent, state, status, null)
            {
            }

            public ProgressableState(Progressable parent, object state, string status, Action callback)
            {
                _parent = parent;
                _state = state;
                _status = status;
                if (!string.IsNullOrEmpty(_status))
                {
                    _parent.AddStatus(_status);
                }
                _callback = callback;
            }

            public object State
            {
                get { return _state; }
            }

            public string Status
            {
                get { return _status; }
            }

            #region IDisposable Members

            public void Dispose()
            {
                if (_callback != null)
                {
                    _parent.Context.Send(delegate { _callback(); }, null);
                }
                if (!string.IsNullOrEmpty(Status))
                {
                    _parent.RemoveStatus(Status);
                }
                GC.SuppressFinalize(this);
            }

            #endregion

            ~ProgressableState()
            {
                Dispose();
            }
        }

        #endregion
    }
}